using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

using DomainModel.Abstract;
using DomainModel.Concrete;
using DomainModel.Entities;
using WebCore.Attributes;
using WebCore;
using WebCore.Helpers;
using WebCore.Caching;
using System.Web.Script.Serialization;
using System.Text;
using System.Web;
using WebCore.Services;
using System.Collections;


namespace WebController.Controllers
{
    public class EventController : _baseController
    {
        private IEventsRepository _eventsRepository = new EventsRepository();
        private IEventsRSVPRepository _eventsRSVPRepository = new EventsRSVPRepository();
        private ICommentsRepository _commentsRepository = new CommentsRepository();


        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult ICSFile(int id)
        {
            var item = GetEventByID(id);
            
            // set the url
            string url = Url.GetBaseUrl();
            url += Url.RouteUrl(new { controller = "Event", action = "Details", id = item.EventID, title = item.Title, });
            
            var ics = new CalendarHelper();
            return File(ics.BuildICS(item, url).ToArray(), "application/ics", item.EventID + "_PopEvent" + ".ics");
        }


        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Details(int? id)
        {
            int eventID = id ?? -1;

            var myEvent = GetEventByID(eventID);

            // no data is found
            if (myEvent == null)
                return RedirectToAction("PageNotFound", "Error");

            return View(myEvent);
        }

        private Event GetEventByID(int id)
        {
            string key = string.Format(Settings.Cache_Event_By_ID_Key, id);

            var myEvent = WebCache.Get(key);

            if (Settings.CacheEnabled && myEvent != null)
            {
                return (Event)myEvent;
            }
            else
            {
                myEvent = _eventsRepository.Get(id);

                // add cache
                WebCache.Add(key, myEvent);

                return (Event)myEvent;
            }
        }

        /// <summary>
        /// send events for goole map makers
        /// </summary>
        /// <returns></returns>
        /// // http://stackoverflow.com/questions/264216/-getjson-returning-cached-data-in-ie8

        [OutputCache(Duration = 0, VaryByParam = "None")]
        public JsonResult JsonGetAllEvents(string page)
        {
            return Json(GetDataByPage(page), JsonRequestBehavior.AllowGet);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Index(string page)
        {
            var event_page = GetDataByPage(page);
            return View(event_page);

        }

        private IEnumerable<Event> GetDataByPage(string page)
        {

            // set pagenumber as 1 if it is null
            int pageNumber = string.IsNullOrEmpty(page) ? 1 : int.Parse(page);
            ViewData["PageNumber"] = pageNumber;

            var list = GetAllEvents();

            int numItems = list.Count();
            ViewData["TotalPages"] = (int)Math.Ceiling((double)numItems / Settings.EventPageSize);
            ViewData["CurrentPage"] = pageNumber;
            ViewData["TotalItemsInCegory"] = numItems;


            var event_page = list.Skip((pageNumber - 1) * Settings.PageSize)
                    .Take(Settings.PageSize);
            return event_page;
        }


        /// <summary>
        /// Load all the event which are not expired
        /// </summary>
        /// <returns></returns>
        private IEnumerable<Event> GetAllEvents()
        {
            string key = string.Format(Settings.Cache_Event_By_ID_Key, "all");

            var cacheObject = WebCache.Get(key);

            if (Settings.CacheEnabled && cacheObject != null)
            {
                return (IEnumerable<Event>)cacheObject;
            }

            var myEvents = _eventsRepository.GetAll();//.Where(x => x.DateEvent > DateTime.Now);

            // add cache
            WebCache.Add(key, myEvents);

            return myEvents;
        }



        #region Create and Edit Events

        [AcceptVerbs(HttpVerbs.Get)]
        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult Create()
        {
            var myEvent = new Event()
            {
                DateEvent = DateTime.Now.AddDays(7)
            };

            return View(myEvent);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult EventEdit(int id, bool? isAdmin)
        {
            bool isAdminTemp = isAdmin ?? false;

            // get data
            var myEvent = _eventsRepository.Get(id);

            foreach (var tag in myEvent.TagsList.OfType<Tag>().OrderBy(x=>x.TagName))
            {
                myEvent.TagString += tag.TagName + ", ";
            }

            // if admin edit this item add edited by 
            if (isAdminTemp)
                myEvent.EditedBy = _user.UserID;

            return View(myEvent);
        }


        // TODO: others could delete the event just giving the ID
        [AcceptVerbs(HttpVerbs.Get)]
        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult EventDelete(int id)
        {
            // check is this item created by this user or admin
            var item = _eventsRepository.Get(id);
            if (UserHelper.IsCreatedByUserID(item.UserID) || UserHelper.IsAdminUser())
            {
                _eventsRepository.Delete(id);
                EventHelper.RemoveAllEventCache();

                return RedirectToAction("Index");
            }
            else
            {
                return RedirectToAction("AccessDenied", "error");
            }



        }

        [AcceptVerbs(HttpVerbs.Post)]
        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult EventEdit(Event item)
        {
            if (ModelState.IsValid)
            {
                // create a new event based on current user
                if (item.UserID == 0)
                {
                    item.UserID = _user.UserID;
                }

                if (item.EditedBy != 0)
                {
                    // edit by admin or user
                    item.EditedBy = _user.UserID;
                }

                var now = DateTime.Now;
                item.DateEditedBy = now;
                item.DateUpdated = now;

                TagService.AddTagsToEvent(item.TagString, item);

                _eventsRepository.Save(item);

                // remove cache
                EventHelper.RemoveAllEventCache();

                return RedirectToAction("Index");
            }
            else
            {
                // Validation error, so redisplay same view
                return View(item);
            }
        }


        #endregion


        [AcceptVerbs(HttpVerbs.Get)]
        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult RemoveUser(int eventID, string returnURL)
        {

            //// only allow to delete owns
            //if (_user.UserID !=userID )
            //    return View("AccessDennied");

            _eventsRSVPRepository.DeleteByEventIDAndUserID(eventID, _user.UserID);

            // remove cache
            EventHelper.RemoveAllEventCache();

            return ReturnURL(returnURL);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult AddUser(int eventID, string returnURL)
        {

            //// only allow to delete owns
            //if (_user.UserID != userID)
            //    return View("AccessDennied");

            // new object
            var item = new EventRSVP();
            item.EventID = eventID;
            item.UserID = _user.UserID;
            item.DateUpdated = DateTime.Now;

            _eventsRSVPRepository.Save(item);

            // remove cache
            EventHelper.RemoveAllEventCache();

            return ReturnURL(returnURL);
        }

        // TODO: duplicate in ratecontroller
        private ActionResult ReturnURL(string returnURL)
        {
            if (!String.IsNullOrEmpty(returnURL))
            {
                return Redirect(returnURL);
            }
            else
            {
                return RedirectToAction("Index", "Event");
            }
        }

        #region comments


        [AcceptVerbs(HttpVerbs.Post)]
        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult Comment(FormCollection form, Event item)
        {
            string content = form["content"].Trim();

            // TODO: add validation
            if (string.IsNullOrEmpty(content))
            {
                TempData["ErrorMessage"] = "no comments?";
                return RedirectToAction ("Details", new { id = item.EventID });
            }

                var comment = new Comment()
                {
                    Content = content,
                    UserID = _user.UserID,
                    DateCreated = DateTime.Now,
                    EventID = item.EventID
                };
                _commentsRepository.Save(comment);

                // remove cache
                EventHelper.RemoveAllEventCache();
          

            return RedirectToAction("Details", new { id = item.EventID });
        }

        [CustomAuthorize(Roles = WebRoles.User | WebRoles.Admin)]
        public ActionResult CommentDelete(int id)
        {

            // check is this item created by this user or admin
            var comment = _commentsRepository.Get(id);
            var eventID = comment.EventID;
            if (UserHelper.IsCreatedByUserID(comment.UserID) || UserHelper.IsAdminUser())
            {
                _commentsRepository.Delete(id);
                EventHelper.RemoveAllEventCache();

                return RedirectToAction("Details", new { id = eventID });
            }
            else
            {
                return RedirectToAction("AccessDenied", "Error");
            }

        }


        #endregion


    }
}
